﻿using System;
using System.Collections.Generic;
using System.Linq;
using SIG.Model;
using SIG.Repository;
using SIG.Infrastructure.Logging;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Resources.Admin;

namespace SIG.Service
{
    public class ProductService: EntityService<Product>, IProductService
    {
       
        private readonly IProductRepository _productRepository;
        private readonly ICategoryRepository _categoryRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public ProductService(IProductRepository productRepository, ICategoryRepository categoryRepository,ILoggingService loggingService, 
            ICacheService cacheService)
            : base( productRepository, cacheService, loggingService)
        {
           
            _productRepository = productRepository;
            _categoryRepository = categoryRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }


        //public IEnumerable<Category> GetCategories()
        //{
        //    // return _unitOfWork.GetRepository<Category>().GetAll();
        //    return _categoryRepository.GetAll();
        //} 

        public Product GetProductByIdWithCategories(int id)
        {
          
            var key = $"{EntityNames.Product}_Categories_{id}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetFirstOrDefault((p=>p.Id == id),(p=>p.Categories));
            }           

            if (_cacheService.IsSet(key))            
                return (Product)_cacheService.Get(key);
          

            Product product = _productRepository.GetFirstOrDefault((p => p.Id == id), (p => p.Categories));
            _cacheService.Set(key, product, SettingsManager.Product.CacheDuration);
           
            return product;
        }

        public IList<Product> SearchProducts(int pageIndex, int pageSize)
        {
            var key = $"{EntityNames.Product}s_Search_{pageIndex}_{pageSize}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.Id), true).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Product>)_cacheService.Get(key);

            }

            List<Product> products = _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.Id), true).ToList();
            _cacheService.Set(key, products, SettingsManager.Product.CacheDuration);

            return products;
        }

        public IList<Product> SearchProducts(int pageIndex, int pageSize, int catId)
        {
            if (catId == 0)
                return SearchProducts(pageIndex, pageSize);

            var key = $"{EntityNames.Product}s_Search_{pageIndex}_{pageSize}_{catId}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetPagedElements(pageIndex,pageSize,(p=>p.Id),(p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId)),true).ToList();
            }            

            if (_cacheService.IsSet(key))
            {
                return (List<Product>)_cacheService.Get(key);

            }
           
            List<Product> products = _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.Id), (p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId)), true).ToList();
            _cacheService.Set(key, products, SettingsManager.Product.CacheDuration);        

            return products;
        }
        public int SearchProductsCount()
        {

            var key = $"{EntityNames.Product}s_SearchCount";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetAllElements().Count();
            }

            if (_cacheService.IsSet(key))
            {
                return (int)_cacheService.Get(key);
            }

            int productsCount = _productRepository.GetAllElements().Count();
            _cacheService.Set(key, productsCount, SettingsManager.Product.CacheDuration);

            return productsCount;
        }

        public int SearchProductsCount(int catId)
        {
            if (catId == 0)
                return SearchProductsCount();
                
            var key = $"{EntityNames.Product}s_SearchCount_{catId}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetFilteredElements((p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId))).Count();
            }

            if (_cacheService.IsSet(key))
            {
                return (int)_cacheService.Get(key);
            }
           
                int productsCount = _productRepository.GetFilteredElements((p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId))).Count();
                _cacheService.Set(key, productsCount, SettingsManager.Product.CacheDuration);
         
            return productsCount;
        }


      

        public IList<Product> GetActiveProducts(int pageIndex, int pageSize)
        {
            var key = $"{EntityNames.Product}s_Active_{pageIndex}_{pageSize}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.CreatedDate), (p => p.Active), false, (p=>p.Categories)).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Product>)_cacheService.Get(key);

            }

            List<Product> products = _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.CreatedDate), (p => p.Active), false, (p => p.Categories)).ToList();
            _cacheService.Set(key, products, SettingsManager.Product.CacheDuration);

            return products;
        }

        public int GetActiveProductsCount()
        {
         
            var key = $"{EntityNames.Product}s_ActiveCount";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetFilteredElements((p => p.Active)).Count();
            }

            if (_cacheService.IsSet(key))
            {
                return (int)_cacheService.Get(key);
            }

            int productsCount = _productRepository.GetFilteredElements((p => p.Active)).Count();
            _cacheService.Set(key, productsCount, SettingsManager.Product.CacheDuration);

            return productsCount;
        }



        public IList<Product> GetActiveProducts(int pageIndex, int pageSize, int catId)
        {
            if (catId == 0)
                return GetActiveProducts(pageIndex, pageSize);

            var key = $"{EntityNames.Product}s_Active_{pageIndex}_{pageSize}_{catId}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.Id), (p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId) && p.Active), true).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Product>)_cacheService.Get(key);

            }

            List<Product> products = _productRepository.GetPagedElements(pageIndex, pageSize, (p => p.Id), (p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId) && p.Active), true).ToList();
            _cacheService.Set(key, products, SettingsManager.Product.CacheDuration);

            return products;
        }


        public int GetActiveProductsCount(int catId)
        {
            if (catId == 0)
                return GetActiveProductsCount();

            var key = $"{EntityNames.Product}s_ActiveCount_{catId}";

            if (!SettingsManager.Product.EnableCaching)
            {
                return _productRepository.GetFilteredElements((p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId) && p.Active)).Count();
            }

            if (_cacheService.IsSet(key))
            {
                return (int)_cacheService.Get(key);
            }

            int productsCount = _productRepository.GetFilteredElements((p => p.Categories.Any(c => c.Id == catId || c.ParentId == catId) && p.Active)).Count();
            _cacheService.Set(key, productsCount, SettingsManager.Product.CacheDuration);

            return productsCount;
        }


      


        public void UpdateProductWithCategory(Product product)
        {
          
            var p = _productRepository.GetFirstOrDefault((prod=> prod.Id == product.Id), (prod => prod.Categories));

            p.ProductNo = product.ProductNo;
            p.ProductName = product.ProductName;
            p.Body = product.Body;
            p.Description = product.Description;
            p.Thumbnail = product.Thumbnail;
          //  p.Keywords = product.Keywords;
            p.Recommend = product.Recommend;
            p.Active = product.Active;
        
            p.PostCategoryIds = product.PostCategoryIds;      
            
            var lCategories = (from c in _categoryRepository.GetAllElements()
                                 where product.PostCategoryIds.Contains(c.Id.ToString())
                                   select c).ToList();

            p.Categories.Clear();
            p.Categories = lCategories;
           
            //foreach (var c in lCategories)
            //{
            //    p.Categories.Add(c);
            //}
            Update(p);
            //_unitOfWork.GetRepository<Product>().Update(product);
            //_unitOfWork.SaveChanges();

            //_cacheService.Invalidate("Product");
            //_loggingService.Info(string.Format(Site.logCreateMessage,Site.Settings.Product.SetName, product.ProductNo, Site.CurrentUserName));
        }

 
    }
}
